#include <gtk/gtk.h>
-static GtkWidget *window = NULL;
-
/* Create an object for the pegs that get moved around in the game.
*
* We implement the GdkPaintable interface for them, so we can use GtkPicture
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
+static int
+solitaire_peg_get_intrinsic_width (GdkPaintable *paintable)
+{
+ return 32;
+}
+
+static int
+solitaire_peg_get_intrinsic_height (GdkPaintable *paintable)
+{
+ return 32;
+}
+
static void
solitaire_peg_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = solitaire_peg_snapshot;
iface->get_flags = solitaire_peg_get_flags;
+ iface->get_intrinsic_width = solitaire_peg_get_intrinsic_width;
+ iface->get_intrinsic_height = solitaire_peg_get_intrinsic_height;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
return TRUE;
}
+static void
+create_board (GtkWidget *window)
+{
+ GtkWidget *grid;
+ GtkWidget *image;
+ int x, y;
+ GtkDragSource *source;
+ GtkDropTarget *target;
+
+ grid = gtk_grid_new ();
+ gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+ gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
+ gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
+ gtk_window_set_child (GTK_WINDOW (window), grid);
+
+ for (x = 0; x < 7; x++)
+ {
+ for (y = 0; y < 7; y++)
+ {
+ if ((x < 2 || x >= 5) && (y < 2 || y >= 5))
+ continue;
+
+ image = gtk_image_new ();
+ gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
+ if (x != 3 || y != 3)
+ {
+ SolitairePeg *peg = solitaire_peg_new ();
+ solitaire_peg_set_position (peg, x, y);
+ gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg));
+ }
+
+ gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1);
+
+ /* Set up the drag source.
+ * This is rather straightforward: Set the supported actions
+ * (in our case, pegs can only be moved) and connect all the
+ * relevant signals.
+ * And because all drag'n'drop handling is done via event controllers,
+ * we need to add the controller to the widget.
+ */
+ source = gtk_drag_source_new ();
+ gtk_drag_source_set_actions (source, GDK_ACTION_MOVE);
+ g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image);
+ g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
+ g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image);
+ gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
+
+ /* Set up the drop target.
+ * This is more involved, because the game logic goes here.
+ */
+
+ /* First we specify the data we accept: pegs.
+ * And we only want moves.
+ */
+ target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE);
+ /* Then we connect our signals.
+ */
+ g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image);
+ g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image);
+ /* Finally, like above, we add it to the widget.
+ */
+ gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target));
+ }
+ }
+}
+
+static void
+restart_game (GtkButton *button,
+ GtkWidget *window)
+{
+ create_board (window);
+}
+
GtkWidget *
do_peg_solitaire (GtkWidget *do_widget)
{
+ static GtkWidget *window = NULL;
+
if (!window)
{
GtkWidget *header;
GtkWidget *restart;
- GtkWidget *grid;
- GtkWidget *image;
- int x, y;
- GtkDragSource *source;
- GtkDropTarget *target;
+
+ window = gtk_window_new ();
restart = gtk_button_new_from_icon_name ("view-refresh-symbolic");
- g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL);
+ g_signal_connect (restart, "clicked", G_CALLBACK (restart_game), window);
header = gtk_header_bar_new ();
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
- window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Peg Solitaire");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
- grid = gtk_grid_new ();
- gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
- gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
- gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
- gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
- gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
- gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
- gtk_window_set_child (GTK_WINDOW (window), grid);
-
- for (x = 0; x < 7; x++)
- {
- for (y = 0; y < 7; y++)
- {
- if ((x < 2 || x >= 5) && (y < 2 || y >= 5))
- continue;
-
- image = gtk_image_new ();
- if (x != 3 || y != 3)
- {
- SolitairePeg *peg = solitaire_peg_new ();
- solitaire_peg_set_position (peg, x, y);
- gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg));
- }
-
- gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1);
-
- /* Set up the drag source.
- * This is rather straightforward: Set the supported actions
- * (in our case, pegs can only be moved) and connect all the
- * relevant signals.
- * And because all drag'n'drop handling is done via event controllers,
- * we need to add the controller to the widget.
- */
- source = gtk_drag_source_new ();
- gtk_drag_source_set_actions (source, GDK_ACTION_MOVE);
- g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image);
- g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
- g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image);
- gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
-
- /* Set up the drop target.
- * This is more involved, because the game logic goes here.
- */
-
- /* First we specify the data we accept: pegs.
- * And we only want moves.
- */
- target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE);
- /* Then we connect our signals.
- */
- g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image);
- g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image);
- /* Finally, like above, we add it to the widget.
- */
- gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target));
- }
- }
+ create_board (window);
}
if (!gtk_widget_get_visible (window))